//
//  BEOperatorExtension.swift
//  BasicExtensions
//
//  Created by JY_NEW on 2022/3/3.
//

import Foundation

// MARK: 操作符重载

precedencegroup BENilCoalescingLeftPrecedence {
    lowerThan: NilCoalescingPrecedence
    associativity: left
}
precedencegroup BENilCoalescingRightPrecedence {
    lowerThan: NilCoalescingPrecedence
    associativity: right
}

///左侧不为空则返回左侧，左侧为空则将右侧执行完赋值给左侧并返回，优先及同??
infix operator ??<: BENilCoalescingRightPrecedence
///左侧不为空则执行右侧的操作返回右侧的值，否则返回nil
infix operator ??>: BENilCoalescingLeftPrecedence
/// 左侧若为空则赋值给左侧，否则左侧不变
infix operator ??= : AssignmentPrecedence
/// 右侧若不为空则赋值给左侧，否则左侧不变
infix operator =?? : AssignmentPrecedence
///只用可空类型(字符串、数组、字典)，在??的基础上添加空(isEmpty)判断
infix operator ???: BENilCoalescingLeftPrecedence
/// 左侧不为空则执行 += 操作，为空则执行 = 操作
infix operator ?+=: AssignmentPrecedence
/// 右侧不为空则执行 += 操作，为空不执行
infix operator +=?: AssignmentPrecedence
/// 两侧不为空执行 += 操作，左侧为空则执行 = 操作，右侧为空则不执行操作
infix operator ?+=?: AssignmentPrecedence

///左侧不为空则返回左侧，左侧为空则将右侧执行完赋值给左侧并返回
@discardableResult
public func ??< <T>(optional: inout T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T? {
    switch optional {
    case .some(let value):
        return value
    case .none:
        if let value = try defaultValue() {
            optional = value
            return value
        }else{
            return nil
        }
    }
}
///左侧不为空则返回左侧，左侧为空则将右侧执行完赋值给左侧并返回
@discardableResult
public func ??< <T>(optional: inout T?, defaultValue: @autoclosure () throws -> T) rethrows -> T {
    switch optional {
    case .some(let value):
        return value
    case .none:
        let value = try defaultValue()
        optional = value
        return value
    }
}

fileprivate enum __OptionalMapError: Error { case unwrappedNil }
fileprivate func __throwsMap<T>(_ input: T?) throws(__OptionalMapError) -> T {
    if let input {
        return input
    }
    throw .unwrappedNil
}
///左侧所有值都不为空则执行右侧的操作返回右侧的值，否则返回nil
@discardableResult
public func ??> <each TI, TO>(optionals: (repeat (each TI)?), result: (repeat each TI) -> TO?) -> TO? {
    do {
        return result(repeat try __throwsMap(each optionals))
    } catch {
        // 有异常说明有非空的字段
        return nil
    }
}

///左侧不为空则执行右侧的操作并返回两个值的组合
@discardableResult
public func ??> <T1, T2>(optionals: [T1?], result: ([T1]) throws -> T2?) rethrows -> T2? {
    var t1s: [T1] = []
    for op in optionals {
        if let t1 = op {
            t1s.append(t1)
        }else {
            return nil
        }
    }
    return try result(t1s)
}

/// 左侧若为空则赋值给左侧，否则左侧不变
public func ??= <T>(left: inout T?, right: @autoclosure () throws -> T) rethrows {
    if left == nil {
        left = try right()
    }
}
/// 左侧若为空则赋值给左侧，否则左侧不变
public func ??= <T>(left: inout T?, right: @autoclosure () throws -> T?) rethrows {
    if left == nil {
        left = try right()
    }
}
/// 右侧若不为空则赋值给左侧，否则左侧不变
public func =?? <T>(left: inout T, right: T?) {
    if let right = right {
        left = right
    }
}
/// 右侧若不为空则赋值给左侧，否则左侧不变
public func =?? <T>(left: inout T?, right: T?) {
    if let right = right {
        left = right
    }
}

///在??的基础上添加空(isEmpty)判断
@discardableResult
public func ??? <T: BEEmptiable>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T {
    switch optional {
    case .some(let value1):
        if !value1.isEmpty {
            return value1
        }
    default: break
    }
    return try defaultValue()
}
///判断isEmpty
@discardableResult
public func ??? <T: BEEmptiable>(value: T, defaultValue: @autoclosure () throws -> T) rethrows -> T {
    if !value.isEmpty {
        return value
    }
    return try defaultValue()
}

/// 左侧不为空则执行 += 操作，为空则执行 = 操作
@discardableResult
public func ?+= <T: BEAddable> (optional: inout T?, target: T) -> T {
    let result: T
    if let old = optional {
        result = old + target
    } else {
        result = target
    }
    optional = result
    return result
}
/// 左侧不为空则执行 += 操作，为空则执行 = 操作
@discardableResult
public func ?+= <T> (optional: inout Array<T>?, target: T) -> Array<T> {
    return optional ?+= [target]
}
/// 左侧不为空则执行 += 操作，为空则执行 = 操作
@discardableResult
public func ?+= <T> (optional: inout Array<T>?, target: (array: Array<T>, index: Int)) -> Array<T> {
    let result: Array<T>
    if var old = optional {
        old.insert(contentsOf: target.array, at: target.index)
        result = old
    } else {
        result = target.array
    }
    optional = result
    return result
}
/// 左侧不为空则执行 += 操作，为空则执行 = 操作
@discardableResult
public func ?+= <T> (optional: inout Array<T>?, target: (element: T, index: Int)) -> Array<T> {
    return optional ?+= ([target.element], target.index)
}
/// 左侧不为空则执行 += 操作，为空则执行 = 操作
@discardableResult
public func ?+= <Key, Value> (optional: inout Dictionary<Key, Value>?, target: (key: Key, value: Value)) -> Dictionary<Key, Value> {
    if optional != nil {
        optional![target.key] = target.value
    } else {
        optional = [target.key: target.value]
    }
    return optional!
}

/// 右侧不为空则执行 += 操作，为空则不执行操作
@discardableResult
public func +=? <T: BEAddable> (value: inout T, target: T?) -> T {
    if let target = target {
        value = value + target
    }
    return value
}
/// 右侧不为空则执行 += 操作，为空则不执行操作
@discardableResult
public func +=? <T> (array: inout Array<T>, target: T?) -> Array<T> {
    if let target = target {
        array.append(target)
    }
    return array
}
/// 右侧不为空则执行 += 操作，为空则不执行操作
@discardableResult
public func +=? <T> (array: inout Array<T>, target: (array: Array<T>?, index: Int)) -> Array<T> {
    if let targetArray = target.array {
        array.insert(contentsOf: targetArray, at: target.index)
    }
    return array
}
/// 右侧不为空则执行 += 操作，为空则不执行操作
@discardableResult
public func +=? <T> (array: inout Array<T>, target: (element: T?, index: Int)) -> Array<T> {
    if let element = target.element {
        array.insert(element, at: target.index)
    }
    return array
}
/// 右侧不为空则执行 += 操作，为空则不执行操作
@discardableResult
public func +=? <Key, Value> (dictionary: inout Dictionary<Key, Value>, target: (key: Key, value: Value?)) -> Dictionary<Key, Value> {
    if let value = target.value {
        dictionary[target.key] = value
    }
    return dictionary
}

/// 两侧不为空执行 += 操作，左侧为空则执行 = 操作，右侧为空则不执行操作
@discardableResult
public func ?+=? <T: BEAddable> (optional: inout T?, target: T?) -> T? {
    if let target = target {
        return optional ?+= target
    }
    return optional
}
/// 两侧不为空执行 += 操作，左侧为空则执行 = 操作，右侧为空则不执行操作
@discardableResult
public func ?+=? <T> (optional: inout Array<T>?, target: T?) -> Array<T>? {
    if let target = target {
        return optional ?+= target
    }
    return optional
}
/// 两侧不为空执行 += 操作，左侧为空则执行 = 操作，右侧为空则不执行操作
@discardableResult
public func ?+=? <T> (optional: inout Array<T>?, target: (array: Array<T>?, index: Int)) -> Array<T>? {
    if let array = target.array {
        return optional ?+= (array, target.index)
    }
    return optional
}
/// 两侧不为空执行 += 操作，左侧为空则执行 = 操作，右侧为空则不执行操作
@discardableResult
public func ?+=? <T> (optional: inout Array<T>?, target: (element: T?, index: Int)) -> Array<T>? {
    if let element = target.element {
        return optional ?+= (element, target.index)
    }
    return optional
}
/// 两侧不为空执行 += 操作，左侧为空则执行 = 操作，右侧为空则不执行操作
@discardableResult
public func ?+=? <Key, Value> (optional: inout Dictionary<Key, Value>?, target: (key: Key, value: Value?)) -> Dictionary<Key, Value>? {
    if let value = target.value {
        return optional ?+= (target.key, value)
    }
    return optional
}
